package org.example;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.example.bean.*;
import org.example.util.*;

import javax.swing.*;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;

public class Main {
    private static final String CONFIG_DIR = "src/main/resources/MapTilesData.json";

    public static void main(String[] args) throws InterruptedException {
        GameMap gameMap = new GameMap(-0, 1035, -0, 1035);
        initMap(gameMap);
        //List<Polygon> polygons = PolygonUtil.findPolygons(gameMap.getMaps());

        // 创建并显示PolygonDrawer
        //PolygonDrawer drawer = new PolygonDrawer(polygons, gameMap.getWeight(), gameMap.getHeight());

        GameHashMap gameHashMap = new GameHashMap(-0, 1035, -0, 1035);
        initHashMap(gameHashMap);
        long now = System.currentTimeMillis();


        //List<JsonGamePos> roads = AStarUtil.findRoads(gameMap.maps, new Node(1, 1), new Node(10, 10));
        //*****************AStar
        /*Node start = new Node(1, 1);
        Node goal = new Node(110, 110);
        List<Node> path = AStarSearch.astar(gameMap.maps, start, goal);
        if (path == null || path.isEmpty()) {
            System.out.println("a*寻路失败：");
        }
        System.out.println("a*寻路结束 耗时：" + (System.currentTimeMillis() -now));
        //画图
        if (path != null ) {
            List<Cord> list = new ArrayList<>(path.size());
            for (Node node : path) {
                list.add(new Cord(node.x, node.y));
            }
            SwingUtilities.invokeLater(() -> {
                GridMapDrawing gameDraw = new GridMapDrawing(gameMap.maps, list, "a*寻路");
                gameDraw.setVisible(true);
            });
        }*/

        //******************RRT
        /*now = System.currentTimeMillis();
        List<RRT.Node> nodes = RRT.rrtSearch(gameMap.maps, 1, 1, 110, 110);
        if (nodes == null || nodes.isEmpty()) {
            System.out.println("rrt寻路失败");
        }
        System.out.println("rrt寻路结束 耗时：" + (System.currentTimeMillis() -now));
        if (nodes != null){
            List<Cord> list = new ArrayList<>();
            for (RRT.Node node : nodes) {
                list.add(new Cord((int) node.x, (int) node.y));
            }
            SwingUtilities.invokeLater(() -> {
                GridMapDrawing gameDraw = new GridMapDrawing(gameMap.maps, list, "寻路");
                gameDraw.setVisible(true);
            });
        }*/

        /*now = System.currentTimeMillis();
        List<int[]> ints = JumpPointSearch.jumpPointSearch(gameMap.maps, 1, 1, 110, 110);
        if (ints == null || ints.size() <= 0) {
            System.out.println("jps 寻路失败");
        }
        System.out.println("jps寻路结束 耗时：" + (System.currentTimeMillis() -now));*/


        now = System.currentTimeMillis();
        LazyNode acquire1 = gameHashMap.getLazyNodePool().acquire();
        acquire1.setX(20);
        acquire1.setY(20);
        LazyNode acquire2 = gameHashMap.getLazyNodePool().acquire();
        acquire2.setX(930);
        acquire2.setY(450);

        List<JsonGamePos> hashpath = ThetaStarHashUtil.findPath(acquire1, acquire2, gameHashMap);
          System.out.println("ThetaStarHashUtil 耗时：" + (System.currentTimeMillis() - now));
        //画图
        if (hashpath != null) {
            List<Cord> list = new ArrayList<>(hashpath.size());
            for (JsonGamePos node : hashpath) {
                list.add(new Cord((int) node.getX(), (int) node.getZ()));
            }
            SwingUtilities.invokeLater(() -> {
                MapDrawing gameDraw = new MapDrawing(gameMap.getMaps(), list, "ThetaStarHashUtil 寻路");
                gameDraw.setVisible(true);
            });
        }

        /*now = System.currentTimeMillis();
        List<LazyNode> path1 = ThetaStarUtil.findPath(new LazyNode(20, 20), new LazyNode(1000, 1000), gameMap);
        System.out.println("ThetaStarUtil 耗时：" + (System.currentTimeMillis() - now));
        //画图
        if (path1 != null) {
            List<Cord> list = new ArrayList<>(path1.size());
            for (LazyNode node : path1) {
                list.add(new Cord((int) node.getX(), (int) node.getY()));
            }
            SwingUtilities.invokeLater(() -> {
                MapDrawing gameDraw = new MapDrawing(gameMap.getMaps(), list, "ThetaStarUtil寻路");
                gameDraw.setVisible(true);
            });
        }*/


        /*now = System.currentTimeMillis();
        List<JsonGamePos> path3 = LazyThetaStarUtil.findPath(new LazyNode(1, 1), new LazyNode(3000, 3000), gameMap);
        System.out.println("LazyThetaStarUtil 耗时：" + (System.currentTimeMillis() - now));
        //画图
        if (path3 != null) {
            List<Cord> list = new ArrayList<>(path3.size());
            for (JsonGamePos node : path3) {
                list.add(new Cord((int) node.getX(), (int) node.getZ()));
            }
            SwingUtilities.invokeLater(() -> {
                GridMapDrawing gameDraw = new GridMapDrawing(gameMap.getMaps(), list, "LazyThetaStarUtil寻路");
                gameDraw.setVisible(true);
            });
        }*/


//        now = System.currentTimeMillis();
//        List<JsonGamePos> path2 = ThetaStarLos.findPath(new LazyNode(20, 20), new LazyNode(850, 850), gameMap);
//        System.out.println("ThetaStarLos 耗时：" + (System.currentTimeMillis() -now));
//        //画图
//        if (path2 != null ) {
//            List<Cord> list = new ArrayList<>(path2.size());
//            for (JsonGamePos node : path2) {
//                list.add(new Cord((int) node.getX(), (int) node.getZ()));
//            }
//            SwingUtilities.invokeLater(() -> {
//                MapDrawing gameDraw = new MapDrawing(gameMap.getMaps(), list, "ThetaStarLos寻路");
//                gameDraw.setVisible(true);
//            });
//        }


    }

    /**
     * 生成地图数据
     *
     * @param map
     */
    private static void initMap(GameMap map) {
        String mapJson = getConfigAsString();
        JSONObject jsonObject = JSONObject.parseObject(mapJson);
        Object tilesDatas = jsonObject.get("tilesDatas");
        if (tilesDatas instanceof JSONArray) {
            JSONArray jsonArray = (JSONArray) tilesDatas;
            for (Object o : jsonArray) {
                JSONObject tile = (JSONObject) o;
                int value = Integer.parseInt((String) tile.get("_func"));
                if (value != 0) {
                    continue;
                }
                String pos = (String) tile.get("_key");
                List<Integer> integers = convertIdsToIntList(pos, ",");
                Integer x = integers.get(0);
                Integer y = integers.get(1);
                map.getMaps()[x][y] = 1;
                /*int indexX = x * 10;
                int indexY = y * 10;
                for (int j = 0; j < 10; j++) {
                    Arrays.fill(map.maps[indexX + j], indexY, indexY + 10, 1);
                }*/
            }
        }
    }

    /**
     * 生成地图数据
     *
     * @param map
     */
    private static void initHashMap(GameHashMap map) {
        String mapJson = getConfigAsString();
        JSONObject jsonObject = JSONObject.parseObject(mapJson);
        Object tilesDatas = jsonObject.get("tilesDatas");
        if (tilesDatas instanceof JSONArray) {
            JSONArray jsonArray = (JSONArray) tilesDatas;
            for (Object o : jsonArray) {
                JSONObject tile = (JSONObject) o;
                int value = Integer.parseInt((String) tile.get("_func"));
                if (value != 0) {
                    continue;
                }
                String pos = (String) tile.get("_key");
                List<Integer> integers = convertIdsToIntList(pos, ",");
                Integer x = integers.get(0);
                Integer y = integers.get(1);
                //添加阻挡
                map.addBlock(x, y);
            }
        }
    }

    /**
     * 读取地图配置
     *
     * @return
     */
    public static String getConfigAsString() {
        String configPath = CONFIG_DIR;
        try {
            byte[] configBytes = Files.readAllBytes(Paths.get(configPath));
            return new String(configBytes);
        } catch (IOException e) {
            e.printStackTrace();
            return "读取异常";
        }
    }

    /**
     * 分割
     *
     * @param ids
     * @param key
     * @return
     */
    public static List<Integer> convertIdsToIntList(String ids, String key) {
        List<Integer> list = new ArrayList<>();
        if (ids == null || ids.length() == 0) {
            return list;
        }
        String[] ps = ids.split(key);
        for (int i = 0; i < ps.length; i++) {
            int id = Integer.parseInt(ps[i]);
            if (id == -1) {
                continue;
            }
            list.add(id);
        }
        return list;
    }

}